/*********************************************************************************
 *      Copyright:  (C) 2023 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file to get sht20.c can.c led.c together.
 *                 
 *        Version:  1.0.0(2023年07月12日)
 *         Author:  Ling Yun <lingyun@email.com>
 *      ChangeLog:  1, Release initial version on "2023年07月12日 13时14分53秒"
 *                 
 ********************************************************************************/

#include "sht20.h"
#include "can.h"
#include "led.h"

/* thread_para结构体，用于之后接受数据时，为创建的线程传入参数 */
struct thread_para
{
	int can_fd;
	struct can_frame rx_frame;
	char *device_name;
};

void print_help(char *arg)
{
	printf("This is a can test program\n");
	printf("usage:%s can0/can1 send/recieve sht20/led\n",arg);
}

/* 解析 sht20 数据并打印 */
int parse_sht20_data(struct can_frame rx_frame)
{
	float	temp;
	float 	rh;

	temp = 175.72 * (((((int) rx_frame.data[0]) << 8) + rx_frame.data[1]) / 65536.0) - 46.85;
	rh = 125 * (((((int) rx_frame.data[3]) << 8) + rx_frame.data[4]) /  65536.0) - 6;
	printf("temperature = %lf relative humidity = %lf\n",temp,rh);
}

/*解析 led 数据并控制led灯 */
int parse_led_data(struct can_frame rx_frame)
{
	if(rx_frame.data[0] == 0x0)
	{
		led_control(0);
	}
	else if(rx_frame.data[0] == 0x1)
	{
		led_control(1);
	}
}

/*  接受数据时创建的线程  */
void *recieve_thread(void *arg)
{
	int		can_fd;
	struct	can_frame rx_frame;
	char	*device_name;

	struct thread_para	*para = (struct thread_para *)arg;

	can_fd = para->can_fd;
	rx_frame = para->rx_frame;
	device_name = para->device_name;

	/*  判断传入的参数，并解析，执行 sht20 和 led 对应的解析函数  */
	for( ; ; )
	{
		if(can_read(can_fd,&rx_frame) == 0)
		{
			if(strcmp(device_name,"sht20") == 0)
			{
				if(rx_frame.can_dlc < 6 )
				{
					printf("the length of data is incorrect\n\n");
					continue;
				}
				parse_sht20_data(rx_frame);
			}
			else if(strcmp(device_name,"led") == 0 )
			{
				parse_led_data(rx_frame);
			}
		}
		printf("\n");
	}
}


int main (int argc, char **argv)
{
	struct can_controller	can_ctrl; //can 控制器结构体
	struct can_frame		frame;	  //can 帧数据，用于数据传输
	struct can_filter		rfilter[1]; //can过滤器
	int						ret;

	int					sht20_fd;
	float				temp;
	float				rh;
	unsigned char		buf_temp[3];
	unsigned char		buf_rh[3];

	/*创建线程所需要的参数*/
	pthread_t			ntid;
	struct thread_para	para;
	int					*thread_ret = NULL;

	if( argc<3 || (strcmp(argv[1],"can0") !=0 && strcmp(argv[1],"can1") != 0))
	{
		print_help(argv[0]);
		return 0;
	}

	/*  通过传入的参数，来使能 can 设备，并设置 can 控制器 */
	can_ctrl.can_name = argv[1];
	can_ctrl.can_fd = can_set_controller(can_ctrl.can_name);
	if(can_ctrl.can_fd < 0)
	{
		printf("fail to set can controller\n");
		return -1;
	}

	/* 如果应用程序用于接受数据 */
	if( 0 == strcmp(argv[2],"recieve"))
	{
		/*  设置 can 过滤器，这里表示 只接受 id 为 0x123 can 从设备发出的数据 */
		rfilter[0].can_id = 0x123;
		rfilter[0].can_mask = 0x7ff;
		setsockopt(can_ctrl.can_fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter , sizeof(rfilter));

		/* 设置创建的线程所需的参数 */
		para.can_fd = can_ctrl.can_fd;
		para.rx_frame = frame;
		para.device_name = argv[3];

		/* 创建新线程并开始接受数据*/
		if(0 == strcmp(argv[3],"sht20"))
		{
			ret = pthread_create(&ntid,NULL,recieve_thread,(void *)(&para));
			if(ret != 0)
			{
				printf("fail to create sht20 recieve thread\n");
			}

			pthread_join(ntid,(void **)&thread_ret);
		}
		else if(0 == strcmp(argv[3],"led"))
		{
			/* 测试时，使用gpio_10 进行led 测试 */
			ret = led_init(1,10);
			if(ret < 0)
			{
				printf("fail to excute led_init\n");
			}
			ret = pthread_create(&ntid,NULL,recieve_thread,(void *)(&para));
			if(ret != 0)
			{
				printf("fail to create sht20 reciece thread\n");
			}

			pthread_join(ntid,(void **)&thread_ret);
		}
		else
		{
			print_help(argv[0]);
			return 0;
		}
	}
	/* 如果应用程序用于接受数据 */
	else if(0 == strcmp(argv[2],"send"))
	{
		/*  设置 socket 为只接受模式  */
		setsockopt(can_ctrl.can_fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

		 /*  如果要发送 sht20 数据，则初始化 sht20，然后获取数据，并使用 can_write 发送数据 */
		if(0 == strcmp(argv[3],"sht20"))
		{
			sht20_fd = sht2x_init();
			if(sht20_fd < 0)
			{
				printf("fail to initialize sht20\n");
				return -1;
			}

			frame.can_dlc = 6;
			/*  测试时，设置接受中使用过滤器，只接受 id 为 0x123 的设备发出的数据，因此此处设置 can_id 为 0x123 */
			frame.can_id = 0x123;

			for( ; ; )
			{
				if(sht2x_get_temp_humidity(sht20_fd,buf_temp,buf_rh, &temp, &rh) < 0)
				{
					printf("fail to get data from sht2x\n");
					return -1;
				}
				frame.data[0] = buf_temp[0];
				frame.data[1] = buf_temp[1];
				frame.data[2] = buf_temp[2];
				frame.data[3] = buf_rh[0];
				frame.data[4] = buf_rh[1];
				frame.data[5] = buf_rh[2];

				can_write(can_ctrl.can_fd, frame);
				printf("\n");
			
				sleep(1);
			}
		}
		 /*  同理，如果发送 led 数据如下  */
		else if( 0 == strcmp(argv[3],"led"))
		{
			frame.can_dlc = 1;
			frame.can_id = 0x123;

			while(1)
			{
				frame.data[0] = 0x1;
				can_write(can_ctrl.can_fd, frame);
				sleep(1);

				frame.data[0] = 0x0;
				can_write(can_ctrl.can_fd, frame);
				sleep(1);
				
				printf("\n");
			}
		}
		else
		{
			print_help(argv[0]);
			return 0;
		}
	}
	else
	{
		print_help(argv[0]);
		return 0;
	}

	//return 0;
} 





